<template>
  <div
    class="custom-tiny-slider"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
  >
    <div ref="container" class="slider" :class="{ hydrated: hydrated }" @click="listenSlideClick">
      <div class="slider__slide" :data-index="index" v-for="(item, index) in data" :key="item.id">
        <div class="box" :class="[`slider-items-${sliderItems}`]">
          <div class="content">
            <nuxt-img :src="item.coverImg" alt="" loading="lazy" class="tns-img" />
          </div>
        </div>
      </div>
    </div>
    <div class="tns-controls" v-if="controls">
      <button class="prev" @click="handlePrev">
        <GIcon name="gt-plane-left" />
      </button>
      <button class="next" @click="handleNext">
        <GIcon name="gt-plane-right" />
      </button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref , computed } from "vue";
import "tiny-slider/dist/tiny-slider.css";
// nuxt 水合完成之后，会自动添加hydrated类,水合之前只展示三个子元素
const hydrated = ref(false);
const props = defineProps<{
  controls?: boolean;
  data: {
    id: string;
    title: string;
    coverImg: string;
    desc?: string;
  }[];
}>();
const emit = defineEmits(["slide-click"]);
const slider = ref(null);
const pauseIng = ref(false);
const dragIng = ref(false);
// 轮播图数量不够4个时每行展示2个，否则每行展示3个
const sliderItems = computed(() => props.data.length < 4 ? 2 : 3);
if (process.client) {
  // 插件包含windows不能在服务端使用
  import("tiny-slider").then((module) => {
    const tns = module.tns;
    slider.value = tns({
      center: true,
      container: ".custom-tiny-slider .slider",
      items: sliderItems.value,
      loop: true,
      mouseDrag: true,
      swipeAngle: false,
      speed: 400,
      autoplay: true,
      autoplayButtonOutput: false,
      nav: true,
      navPosition: "bottom",
      navAsThumbnails: true,
      controls: false,
      onInit: (info) => {
        addActiveClass(info);
      },
    });

    // 监听索引变化事件
    slider.value.events.on("indexChanged", (info) => {
      addActiveClass(info);
    });

    slider.value.events.on("dragMove", () => {
      if (!dragIng.value) {
        dragIng.value = true;
      }
      markDragEnd();
    });
  });
}

function addActiveClass(info) {
  const { index, slideItems, slideCountNew, items, slideCount } = info;
  // console.log(index,info);
  const arr = Array.from(slideItems);
  arr.forEach((item) => {
    item.classList.remove("active");
    item.classList.remove("prev");
    item.classList.remove("next");
  });
  // 编辑当前索引slide的样式,上一个，下一个和active
  editSlideClassByIndex(index, slideItems);

  const lastIndex = slideCountNew - items;
  // 最后一个或者第一个，轮播图克隆元素被移动，手动处理下一个轮播图的样式，过渡效果不流畅
  if (index === 0) {
  const nIndex = index + slideCount;
   editSlideClassByIndex(nIndex, slideItems);
  } else if(index === lastIndex){
    const nIndex = lastIndex - slideCount;
    editSlideClassByIndex(nIndex, slideItems);
  }
}

/**
 * 根据索引编辑轮播图的样式
 * @param index 索引
 * @param slideItems 轮播图元素
 */
function editSlideClassByIndex(index, slideItems) {
  const arr = Array.from(slideItems);
  const prevSlide = arr[index - 1];
  const middleSlide = arr[index];
  const nextSlide = arr[index + 1];
  prevSlide?.classList.add("prev");
  middleSlide?.classList.add("active");
  nextSlide?.classList.add("next");
}

function handlePrev() {
  slider.value.goTo("prev");
  // 点击后会自动回到autoplay，重新暂停
  slider.value?.pause();
}

function handleNext() {
  slider.value.goTo("next");
  // 点击后会自动回到autoplay，重新暂停
  slider.value?.pause();
}

function handleMouseEnter() {
  slider.value?.pause();
}

function handleMouseLeave() {
  slider.value?.play();
}

/**
 * 监听点中的元素，emit 点击事件
 */
function listenSlideClick(e) {
  if (dragIng.value) return;

  // 从点击元素开始向上查找，直到找到带有 data-index 的元素
  let target = e.target;
  while (target && !target.dataset.index) {
    target = target.parentElement;
    // 如果已经查找到了 slider 容器还没找到，就退出
    if (target.classList.contains('slider')) {
      return;
    }
  }
  const index = target.dataset.index;
  if (target && index) {
    emit("slide-click", { slide: props.data[index], index });
  }
}

const markDragEnd = useDebounce(() => {
  dragIng.value = false;
}, 100, { leading: false, trailing: true });

onMounted(() => {
  hydrated.value = true;
});

onBeforeUnmount(() => {
  if (slider.value) {
    slider.value.destroy();
  }
});
</script>

<style lang="scss">
$nav-height: 21px;
/* 元素不能超出容器，使用负值补偿 */
$repair-width: 92px;
$repair-width-md: 72px;
.custom-tiny-slider {
  overflow: hidden;
  position: relative;
  &:hover {
    .tns-controls {
      opacity: 1;
    }
  }
  .tns-inner > .tns-outer > .tns-nav {
    // fix-bug: 切换nav展示多个
    display: none;
  }
  /* 切换按钮 */
  .tns-controls {
    opacity: 0;
    transition: opacity 0.2s ease;
    @media (max-width: 768px) {
      display: none;
    }
    button {
      position: absolute;
      // 50% 减去nav占有高度一般
      top: calc(50% - ($nav-height + 16px) / 2);
      transform: translateY(-50%);
      width: 36px;
      height: 36px;
      border-radius: 50%;
      background-color: rgba(255, 255, 255, 0.8);
      border: none;
      color: #333;
      font-size: 18px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      z-index: 10;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
      transition: opacity 0.3s ease;
      &:hover {
        background-color: #fff;
      }
    }

    .prev {
      left: 20px;
    }

    .next {
      right: 20px;
    }
  }
  // 轮播图小点
  .tns-nav {
    text-align: center;
    height: $nav-height;
    margin-top: 16px;

    button {
      width: 8px;
      height: 8px;
      border-radius: 8px;
      background-color: #e3e3ee;
      margin: 0 4px;
      display: inline-block !important;
      transition: width 0.3s ease;
    }

    .tns-nav-active {
      width: 24px;
      background-color: #3f425a;
    }
  }
  // 轮播图主体
  .slider {
    position: relative;
    height: 320px;
    @media (max-width: 768px) {
      height: 280px;
    }
    @media (max-width: 640px) {
      height: 140px;
    }

    &:not(.hydrated) {
      .slider__slide:nth-child(n + 4) {
        display: none;
      }
      .slider__slide:nth-child(2) {
        .box {
          margin-left: -$repair-width;
          margin-right: -$repair-width;
          @media (max-width: 768px) {
            margin-left: -$repair-width-md;
            margin-right: -$repair-width-md;
          }
        }
      }
    }
    .slider__slide {
      height: 100%;

      .box {
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
      }
      // 左边slide
      &.prev {
        .box {
          z-index: 2;
          // 向右补差值
          margin-right: -$repair-width * 2;
          @media (max-width: 768px) {
            margin-right: -$repair-width-md * 2;
          }
        }
        .content {
          transform-origin: left !important;
        }
      }
      // 右边slide
      &.next {
        .box {
          z-index: 2;
          // 向左补差值
          margin-left: -$repair-width * 2;
          @media (max-width: 768px) {
            margin-left: -$repair-width-md * 2;
          }
        }
        .content {
          transform-origin: right !important;
        }
      }

      .content {
        width: 100%;
        height: 100%;
        overflow: hidden;
        transition: all 0.3s ease-in-out;
        overflow: hidden;
        border-radius: 8px;
        transform: scale(1);
        cursor: pointer;

        .tns-img {
          width: 100%;
          height: 100%;
          border-radius: 8px;
          object-fit: cover;
        }
      }

      &.active {
        .box {
          z-index: 3;
          // 向左右补差值
          margin-left: -$repair-width;
          margin-right: -$repair-width;
          @media (max-width: 768px) {
            margin-left: -$repair-width-md;
            margin-right: -$repair-width-md;
          }
        }
        .content {
        }
      }

      &:not(.active) {
        .content {
          // 大小的高度比
          transform: scale(0.855) !important;
        }
      }
    }
  }
}
</style>
